<?php
/**
 * Created by PhpStorm.
 * User: longli
 * VX: isa1589518286
 * Date: 2020/12/20
 * Time: 15:11
 * @link http://www.lmterp.cn
 */

namespace app\admin\controller\pur;

use app\admin\controller\BaseController;
use app\common\model\FinanceBank;
use app\common\model\FinanceCash;
use app\common\model\Producer;
use app\common\model\Purchase;
use app\common\model\PurchaseException;
use app\common\model\PurchaseInfo;
use app\common\model\PurchaseReturn;
use app\common\service\purchase\RExService;
use think\Db;

/**
 * 采购异常
 * Class ExceptionController
 * @package app\admin\controller\pur
 */
class ExceptionController extends BaseController
{

    protected function loadCommon()
    {
        $this->assign("exception_type", PurchaseException::$EXCEPTION_TYPE);
        $this->assign("dispose_result", PurchaseException::$DISPOSE_RESULT);
        $this->assign("dispose_wait", PurchaseException::POSE_RES_WAIT);
    }

    /**
     * 采购异常
     * @date 2020/12/02
     * @author longli
     */
    public function index()
    {
        if($this->request->isAjax())
        {
            $purchase = Purchase::with(['buyer', 'warehouse', 'recv'])
                ->join(PurchaseException::getTable() . " e", "p.purchase_id=e.purchase_id")
                ->alias("p")
                ->field(["p.*", "exception_type", "e.user_id", "e.remark", "e.dispose_result", "e.sku"])
                ->group(["exception_type", "e.purchase_id"])
                ->order("dispose_result, e.eid desc");
            $this->search($purchase);
            $limit = $this->getPageSize();
            $purchase = $purchase->paginate($limit);
            $this->assign('dispose_wait', PurchaseException::POSE_RES_WAIT);
            $this->assign("list", $purchase->getCollection());
            $this->assign("page", $purchase->render());
            return $this->fetch("lists");
        }
        $this->assign('type_sn', [
            'purchase_sn' => '采购单号',
            'producer_sn' => '供应商单号',
        ]);
        $this->assign("buyers", Purchase::getBuyers());
        $this->assign("producer", Producer::getAll());
        return $this->fetch("index");
    }

    /**
     * 搜索异常
     * @param Purchase $purchase 采购
     * @date 2021/01/21
     * @author longli
     */
    private function search($purchase)
    {
        $this->searchModel($purchase, [
            'eq' => ['exception_type', 'dispose_result', 'producer_id', 'buyer_user_id'],
            'times' => ['recv_date']
        ]);
        if($sn = $this->request->post('sn', '', 'trim'))
        {
            $purchase->whereRaw("purchase_sn=? OR producer_sn=?", [$sn, $sn]);
        }
        if(!empty($data['is_show_dispose'])) $purchase->where("e.user_id", $this->user->id);
    }

    /**
     * 异常详情
     * @date 2021/01/21
     * @author longli
     */
    public function info()
    {
        $purId = $this->request->get("purchase_id");
        if(empty($purId)) $this->error("非法请求");
        $purchase = Purchase::with(["pexceInfo"])->get($purId);
        $this->assign("purchase", $purchase);
        $this->assign("banks", FinanceBank::getAll());
        $this->assign("cash_type", FinanceCash::$CASH_TYPE);
        return $this->fetch("info");
    }

    /**
     * 处理异常
     * @date 2021/01/21
     * @author longli
     */
    public function solve()
    {
        if(($msg = $this->validateSolve()) !== true)
            $this->error($msg);
        $post = $this->combinationData();
        $data = [
            'purchase_id' => $this->request->post('purchase_id'),
            'is_check' => $this->request->post('is_check', 0),
            'account' => FinanceBank::get($this->request->post('bank_id'))->account,
            'cash_type' => FinanceCash::CASH_TYPE_BANK,
            'cash_date' => $this->request->post('cash_date'),
            'desc' => $this->request->post('desc'),
        ];
        try
        {
            Db::startTrans();
            $reService = RExService::getInstance();
            $msg = true;
            // 更新处理结果
            foreach($post['eData'] as $e)
            {
                $reService->addException($e);
                if(in_array($e['dispose_result'], [PurchaseException::POSE_RES_REISSUE, PurchaseException::POSE_RES_EXCHG])
                    && ($pinfo = PurchaseInfo::getBySku($e['sku'], $e['purchase_id'])))
                {
                    $pinfo->store_status = $e['dispose_result'] == PurchaseException::POSE_RES_REISSUE
                        ? PurchaseInfo::STORE_REISSUE
                        : PurchaseInfo::STORE_EXCHANGE;
                    $pinfo->save();
                }
            }
            // 退钱退货
            if(!empty($post['returnMoney']))
            {
                $data['type'] = PurchaseReturn::RETURN_TYPE_PAM;
                $data['logistics_price'] = $post['mp']['rm'];
                $msg = $reService->addReturn($data, $post['returnMoney']);
            }
            // 退钱不退货
            if(!empty($post['return']))
            {
                $data['type'] = PurchaseReturn::RETURN_TYPE_M;
                $data['logistics_price'] = $post['mp']['re'];
                $msg = $reService->addReturn($data, $post['return']);
            }
            // 换货
            if(!empty($post['exchange']))
            {
                unset($data['account']);
                $data['logistics_price'] = $post['mp']['ex'];
                $msg = $reService->addExchange($data, $post['exchange']);
            }
            // 手动确认异常
            if(!empty($post['exception']))
            {
                $reService->abnormal($data['purchase_id'], $post['exception']);
            }
            if($msg !== true && is_string($msg))
            {
                Db::rollback();
                $this->error($msg);
            }
            Db::commit();
            $this->success("异常处理成功");
        }catch (\think\Exception\DbException $exception)
        {
            \think\Facade\Log::info(sprintf("处理异常采购单失败，错误信息【%s】", $exception->getMessage()));
            Db::rollback();
            $this->error("服务器异常，请稍后再试");
        }
    }

    /**
     * 组装数据
     * @return array
     * @date 2021/01/21
     * @author longli
     */
    private function combinationData()
    {
        $post = $this->request->post();
        $eData = $return = $returnMoney = $exchange = $exception = [];
        $re = $rm = $ex = 0;
        // 组装数据
        foreach($post['dispose_result'] as $k => $r)
        {
            $infoData = [
                "sku" => $post['sku'][$k],
                "qty" => $post['qty'][$k],
                "cost_desc" => isset($post['cost_desc'][$k]) ? $post['cost_desc'][$k] : '',
                "remark" => isset($post['remark'][$k]) ? $post['remark'][$k] : '',
            ];
            $logisticsPrice = isset($post['logistics_price'][$k]) && $post['logistics_price'][$k] > 0
                ? $post['logistics_price'][$k]
                : 0;
            if($r == PurchaseException::POSE_RES_RET_M) // 退钱不退货
            {
                $return[] = $infoData;
                $re += $logisticsPrice;
            }
            else if($r == PurchaseException::POSE_RES_RET_PAM)  // 退钱退货
            {
                $returnMoney[] = $infoData;
                $rm += $logisticsPrice;
            }
            else if($r == PurchaseException::POSE_RES_EXCHG)  // 换货
            {
                $exchange[] = $infoData;
                $ex += $logisticsPrice;
            }
            else if(in_array($r, [PurchaseException::POSE_RES_NE, PurchaseException::POSE_RES_AFF_EXE])) // 确认异常
            {
                $exception[] = $infoData;
            }
            $eData[] = [
                'eid' => $post['eid'][$k],
                'dispose_result' => $r,
                'user_id'        => $this->user->id,
                'purchase_id'    => $post['purchase_id'],
                'sku'            => $post['sku'][$k],
            ];
        }
        $mp = compact('re', 'rm', 'ex');
        return compact('mp', 'eData', 'return', 'returnMoney', 'exchange', 'exception');
    }

    /**
     * 验证处理异常数据
     * @return bool|string
     * @date 2021/01/21
     * @author longli
     */
    private function validateSolve()
    {
        $validate = \think\facade\Validate::make([
            'purchase_id'  => 'require',
            'logistics_price'  => 'require|array',
            'bank_id'  => 'require',
            'cash_date'  => 'require',
            'eid'  => 'require|array',
            'sku'  => 'require|array',
            'dispose_result'  => 'require|array',
        ],[
            'purchase_id.require' => '采购单必传',
            'logistics_price.array' => '物流费只能是数组',
            'bank_id.require' => '收款账号必选',
            'cash_date.require' => '应收款日期必传',
            'sku.array' => 'SKU 只能是数组',
            'eid.array' => '处理数据只能是数组',
            'dispose_result.array' => '处理结果只能是数组',
        ]);
        $post = $this->request->post();
        if(!$validate->batch()->check($post)) return join(', ', $validate->getError());
        $error = [];
        foreach($post['sku'] as $k => $sku)
        {
            if(empty($post['dispose_result'][$k])) $error[] = "SKU【{$sku}】处理结果有误";
        }
        if(!empty($error)) return join(", ", $error);
        return true;
    }
}